/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.cfg;

import cn.easyplatform.EntityNotFoundException;
import cn.easyplatform.ServiceException;
import cn.easyplatform.cfg.listener.JmsApplicationListener;
import cn.easyplatform.dao.DaoFactory;
import cn.easyplatform.dao.EntityDao;
import cn.easyplatform.i18n.I18N;
import cn.easyplatform.interceptor.*;
import cn.easyplatform.lang.Nums;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.log.LogManager;
import cn.easyplatform.services.*;
import cn.easyplatform.services.cache.EhCacheManagerService;
import cn.easyplatform.services.system.EntitiesDataSourceSevice;
import cn.easyplatform.shiro.DefaultSessionListener;
import cn.easyplatform.shiro.DefaultSessionManager;
import cn.easyplatform.shiro.DefaultSubjectFactory;
import cn.easyplatform.spi.extension.ApplicationService;
import cn.easyplatform.spi.listener.ApplicationListener;
import cn.easyplatform.type.EntityType;
import cn.easyplatform.util.ConfigTools;
import cn.easyplatform.util.ObfuscatedString;
import org.apache.commons.io.FilenameUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.config.Ini;
import org.apache.shiro.config.Ini.Section;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.AbstractSessionManager;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.io.File;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public abstract class EngineConfiguration {

    protected final Logger log = LoggerFactory.getLogger(EngineConfiguration.class);

    // 核心缓存线程池服务
    private ThreadPoolExecutor kernelThreadPoolExecutor;
    // ///////////具体执行者///////////////////
    protected CommandExecutor commandExecutor;
    // //////////执行工厂///////////////////
    private CommandContextFactory commandContextFactory;
    // /////////系统配置项//////////////////
    private Ini config;
    // /////////注册的服务/////////////////
    protected Map<String, ApplicationService> services = new ConcurrentHashMap<String, ApplicationService>();
    // /////////格式:[appContext:Service]//
    protected Map<String, IProjectService> projectServices = new ConcurrentHashMap<String, IProjectService>();
    // //////////外部注册的服务/////////////
    protected Map<Class<?>, Object> engineServices = new HashMap<Class<?>, Object>();
    // //////////系统缓存//////////////////
    protected Cache<String, Object> applicationCache;
    // 系统属性
    protected Map<String, String> properties;
    //服务器运行模式
    protected boolean standalone;
    //服务侦听者
    private ApplicationListener applicationListener;
    // 对象鑜
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    //缓存管理器
    private ICacheManager cacheManager;
    //Web应用路径
    private String webApps;
    //Web应用前端模板路径
    private String webTemplatePath;
    //Web应用前端工作空间($708|$730)
    private String webWorkspacePath;
    //应用工作空间
    private String appWorkspacePath;
    //引擎模板项目路径
    private String appTemplatePath;
    //私钥
    private PrivateKey privateKey;
    //公钥
    private PublicKey publicKey;

    /**
     * 初始化
     */
    public void init(Map<String, String> args) {
        this.properties = args;
        initShiro();
        initCommandContextFactory();
        initCommandExecutors();
        initEngineService();
    }

    /**
     * 启动应用
     */
    public boolean checkModel() {
        // 参数连接池
        try {
            EntitiesDataSourceSevice ds = new EntitiesDataSourceSevice();
            ds.setEngineConfiguration(this);
            ds.start();
            services.put(ds.getId(), ds);
            return true;
        } catch (Exception e) {
            if (log.isErrorEnabled())
                log.error("checkModel", e);
            return false;
        }
    }

    /**
     *
     */
    private void initShiro() {
        StringBuilder sb = new StringBuilder(properties.get("easyplatform.conf"));
        sb.append(File.separatorChar).append("easyplatform.conf");
        if (log.isInfoEnabled())
            log.info(I18N.getLabel("easyplatform.load.config", sb));
        config = Ini.fromResourcePath(sb.toString());

        if (config.getSection("engine") == null)
            throw new ServiceException(
                    I18N.getLabel("easyplatform.config.invalid"));
        webApps = properties.get("web.apps");
        if (Strings.isBlank(webApps)) {
            webApps = config.getSection("engine").get("web.app.path");
            standalone = false;
        } else
            standalone = true;

        webTemplatePath = config.getSection("engine").get("web.app.template");
        if (Strings.isBlank(webTemplatePath)) {
            if (Strings.isBlank(webApps))
                throw new ServiceException(
                        I18N.getLabel("easyplatform.config.not.found", "web.app.template"));
            webTemplatePath = FilenameUtils.normalize(webApps + "/WEB-INF/template");
        }

        webWorkspacePath = config.getSection("engine").get("web.app.workspace");
        if (Strings.isBlank(webWorkspacePath)) {
            if (Strings.isBlank(webApps))
                throw new ServiceException(
                        I18N.getLabel("easyplatform.config.not.found", "web.app.workspace"));
            webWorkspacePath = webApps + File.separatorChar + getAppPath();
        }

        appWorkspacePath = config.getSection("engine").get("workspace");
        if (Strings.isBlank(appWorkspacePath))
            appWorkspacePath = properties.get("easyplatform.home") + File.separatorChar
                    + "workspace";

        appTemplatePath = config.getSection("engine").get("app.template.path");
        if (Strings.isBlank(appTemplatePath))
            appTemplatePath = appWorkspacePath;

        /*
         * 设置shiro配置项
         */
        // securityManager
        config.setSectionProperty("main", "securityManager",
                DefaultSecurityManager.class.getName());

        // sessionManager
        config.setSectionProperty("main", "sessionDAO",
                "org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO");
        config.setSectionProperty("main", "sessionDAO.activeSessionsCacheName",
                "easyplatform-activeSessionCache");

        // listener
        config.setSectionProperty("main", "sessionListener",
                DefaultSessionListener.class.getName());
        config.setSectionProperty("main", "sessionManager", DefaultSessionManager.class.getName());
        config.setSectionProperty("main", "sessionManager.sessionDAO",
                "$sessionDAO");
        config.setSectionProperty("main", "sessionManager.sessionValidationSchedulerEnabled",
                "false");
        //config.setSectionProperty("main", "sessionManager.sessionValidationInterval",
        //        String.valueOf(Nums.toInt(config.getSection("engine").get("sessionValidationInterval"), 60) * 1000));
        config.setSectionProperty("main", "sessionManager.sessionListeners",
                "$sessionListener");
        config.setSectionProperty("main", "securityManager.sessionManager",
                "$sessionManager");

        // subjectFactory
        config.setSectionProperty("main", "subjectFactory",
                DefaultSubjectFactory.class.getName());
        config.setSectionProperty("main", "securityManager.subjectFactory",
                "$subjectFactory");

        // cacheManager
        String cacheClass = config.getSectionProperty("main", "cacheManager");
        if (Strings.isBlank(cacheClass)) //使用简单的EhCache)
                config.setSectionProperty("main", "cacheManager", EhCacheManagerService.class.getName());

        config.setSectionProperty("main", "securityManager.cacheManager",
                "$cacheManager");

        // sessionValidationScheduler
        /**config.setSectionProperty("main", "sessionValidationScheduler",
         QuartzSessionValidationScheduler.class.getName());
         config.setSectionProperty("main",
         "sessionValidationScheduler.sessionManager", "$sessionManager");
         config.setSectionProperty("main",
         "securityManager.sessionManager.sessionValidationScheduler",
         "$sessionValidationScheduler");
         */
        // easyplatform选项
        //setPlatformOption("sessionValidationInterval",
        //        "sessionValidationScheduler.sessionValidationInterval");
        setPlatformOption("sessionTimeout",
                "securityManager.sessionManager.globalSessionTimeout");

        //设置系统变量
        Section section = config.getSection("engine");
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            section.put(entry.getKey(), entry.getValue());
        }

        //设置日志
        if (config.getSection("log") == null) {
            Section sec = config.addSection("log");
            sec.put("app.size.based", "10 MB");
            sec.put("app.max.rollover", "30");
            sec.put("app.last.modified", "30d");
            sec.put("user.size.based", "10 MB");
            sec.put("user.max.rollover", "30");
            sec.put("user.last.modified", "30d");
        }
        LogManager.setConfiguration(config.getSection("log"));

        Factory<SecurityManager> factory = new IniSecurityManagerFactory(config);
        SecurityUtils.setSecurityManager(factory.getInstance());
        cacheManager = (ICacheManager) ((DefaultSecurityManager) factory.getInstance()).getCacheManager();
        applicationCache = cacheManager.getCache(
                "application");
        //平台核心线程池
        int coreSize = getPlatformAttributeAsInt("kernelCorePoolSize");
        if (coreSize == 0)
            coreSize = Runtime.getRuntime().availableProcessors();
        int maxSize = getPlatformAttributeAsInt("kernelMaximumPoolSize");
        if (maxSize == 0)
            maxSize = coreSize * 2;
        int queueSize = getPlatformAttributeAsInt("kernelQueueSize");
        if (queueSize == 0)
            queueSize = Integer.MAX_VALUE;
        int keepAliveTime = getPlatformAttributeAsInt("kernelKeepAliveTime");
        if (keepAliveTime == 0)
            keepAliveTime = 60 * 1000;//1分钟
        kernelThreadPoolExecutor = new ThreadPoolExecutor(coreSize, maxSize,
                keepAliveTime, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(queueSize));

        Section jmsConfig = config.getSection("jms");
        Section redisConfig = config.getSection("redis");
        if (!standalone && jmsConfig == null && redisConfig == null)
            throw new ServiceException(I18N.getLabel(
                    "easyplatform.listener.not.found"));
        if (jmsConfig != null)
            applicationListener = new JmsApplicationListener(this);
        try {
            File dir = new File(appWorkspacePath);
            if (!dir.exists() || !dir.isDirectory())
                throw new ServiceException(I18N.getLabel(
                        "easyplatform.workspace.invalid", appWorkspacePath));
            //获取非对称密钥对
            privateKey = ConfigTools.getPrivateKey(new ObfuscatedString(new long[]{0x2FA2DE0C938EC80FL, 0xA688181948C3D4FL, 0x2BD4075249B2C919L, 0x78F4C15E0446173L, 0x3EA87CD1A4C99A7AL, 0xB6D446C918A337A7L, 0x704C959A618BD38CL, 0xB7189AD44E399F88L, 0xE97C01D81B6CF4DAL, 0x66A3720A48E345L, 0x3DF7D4EA2426DBC1L, 0xF7E3EEDC5E3E5E5DL, 0x3EE63E090027EEE4L, 0xF25BD69808985C4BL, 0x6D09907409AEEC7DL, 0xE3BCA79300DA76DAL, 0x5F93549028674D77L, 0x61B843517E63A94BL, 0xF3AAC58ACDC3A4F8L, 0xAD426C8F014B38DAL, 0x9D86C178E5448595L, 0x532C6DEA7AA97380L, 0x6DA606BA5E445723L, 0xF2ED4302791AF047L, 0xB05DD7DEFE02B806L, 0x78A9DACF24FC3EA5L, 0x2CE373BCF8F795C1L, 0xE11A83E7127823EL, 0xE2004715DC3739F2L, 0xA85D01B0C5F06D8AL, 0x5D77494F0EBA2088L, 0xC78F8C734D72D75L, 0xA450A49A292FFF92L, 0x54F1E3309D196B18L, 0xD5600CBEE03BB368L, 0x68E0272686A8958BL, 0x7EC1F4A9AF7780F1L, 0xD91DFF119CAEF91L, 0x4A20C24E6E349AD9L, 0x22C8891F39D95B2DL, 0x7B2A304B7DB2FAF7L, 0x42088C254A6252BBL, 0x18BAF965A3818FE5L, 0x9E08097072EEDA8EL, 0x6005957B5CF73621L, 0xB167E9B461E33536L, 0xE722AAA7B36052A0L, 0x4B155F2AFCAD085DL, 0x2E8BE22C4978DEF2L, 0x2FC74E6D9DA78869L, 0x1981360999D7C20L, 0x4412F68B1B41EDDFL, 0xC463440E9C24906CL, 0x5B483E6DF13CE5AEL, 0x635BFB0288C2DE0L, 0xC1DF443DDDE68F7FL, 0xAD06A8C7B0DB971L, 0xE351901F35D23645L, 0x3EA0E44D243FA937L, 0x45A8486D7C68F0ECL, 0x9C6A2F1E85AE7A8L, 0x6D602A15BD516518L, 0xBAFADCB8D302EA98L, 0x2512526BF3E00EA0L, 0x790A7D04F0E70062L, 0xB76867A075EF9C8FL, 0xE72B2D7931B98D95L, 0x4B4B92B71069F2F1L, 0x4FE6C2E21809C316L, 0xCAB63E86824ECC50L, 0xD904DBE4C60AA2DFL, 0x184C2C4C14E01207L, 0x5CCCD86DAE5F7A9CL, 0x8DBDA86FBEB27CE6L, 0xE2023F46AAFA252BL, 0x115E3EA752968809L, 0xA152985C25BE2E4DL, 0x7DF439F6E3EEC28EL, 0xE90A320560102AD0L, 0x75B3F509EEE1EEB1L, 0xA314AE3E0B52DF8CL, 0xD8747D071E0E9CFDL, 0x1650D8E0858689F7L, 0xA6ABCAF13E4F095L, 0xE540FC8EED2D2862L, 0xFFB744C92D5FE346L, 0xD3F564857F7F7828L, 0x16ACD9D1D7791E26L, 0x3B4353AFE1CB8102L, 0xE3D85E312A3ED6C6L, 0x785F5E9A4ED287D5L, 0x8F3E0B3B12FEE48EL, 0x11A6EA52264E960BL, 0xCB9BDF6123F9B9L, 0xF814DE8E93237E23L, 0x7B05E5986701EE6L, 0xE2CC95A8763F3D7L, 0x5DA4CEE4BDA89DBFL, 0x4F05A55ABDE33B72L, 0xD745B54554AB7E91L, 0xA35A62C89C41D119L, 0xF5696655D0A4A7C7L, 0x444685B80613FCA7L, 0xBF0E65568D0C0E1BL, 0xAE5C4FB3F0855B55L, 0xE7A390E6812AF640L, 0xEE7282DBE71FB38DL, 0xEEFC749B7B56B0AAL, 0x7885860B1BB0CD3CL, 0xA0F62ED34F9A556BL, 0xF12FDAE0F42691FEL, 0x65FE576E4023591EL, 0x59C469AFA060A528L, 0x412083246D1A38B0L, 0xFD23A2EFF7B54A9EL, 0xEEAFBFA6FE06E6CAL, 0xB8EE0E79E318F11BL, 0x4A243C6D4E21354L, 0x94FA469F784D8A10L, 0xDF01B05584341470L, 0x7F22060323AE9A46L, 0x3CFB59719D3B4C4AL, 0x54318A3A53A69A09L, 0x118DE2DC23D672F1L, 0x8D7DF54DC61B4A39L, 0x233BBD51411845BL, 0x596B5C5963B8CF69L, 0xFF95E88F52151D5AL, 0x130F0CE68BE95C3AL, 0x87D30B6741E4638FL, 0xAB312B3613FB3062L, 0xA8B7579A35DA8269L, 0xD9A7B8E2F2BFFAC7L, 0x55395E75CFFA9525L, 0xEE1B9652AF11949AL, 0x7B8D58B5DBDCDB36L, 0x4B03A109B819A448L, 0xECB598191F368100L, 0x62A77BB091BBBE0DL, 0x8DA9C369A9E3C5A6L, 0x7876AEC3081F641FL, 0x7814741062C88753L, 0xD9F4954F1D0C3102L, 0xD2131FD87AA858F4L, 0xEFA30F8AA856D4CDL, 0x3BF3A79098EAA55EL, 0x34BB685F405DA57CL, 0x8E982A277D357485L, 0x314A38A0A1ADA518L, 0xF97E31335646B8E8L, 0xE53B87093AA44994L, 0xA862235A662CC21DL, 0xAA13C52AA2196EBAL, 0xEB074BE2756BB213L, 0x156411ADBE8D0E33L, 0x6779E813D83DF6CBL, 0x2C8725A316BF1003L, 0x7ACED3734E74416L, 0x7DF296F973514EBEL, 0xA8B3D18BD6612C48L, 0x5982A248F439F54CL, 0x485EE097864E30D0L, 0x9FABD39BE2A6DE9DL, 0x889453EEBDE90E06L, 0x13A4480E9A96B636L, 0xD2B9B39710901A80L, 0x2E85208FA847957FL, 0x776054CD191AD2C9L, 0x262DAE536CD7D230L, 0x54673599AA349BA9L, 0x61298C0ADED61478L, 0x2D6A64D6F38EF1F5L, 0x71BC46134CB8834AL, 0x43BB3CDDB7BD41D4L, 0xB05556D2B3685B83L, 0x47C44EBEC04C2CEEL, 0x68EA69E0FC7BEDFCL, 0xB00CACF2595FD244L, 0xCE3F93BC485463B6L, 0x5EF1530FF8D29093L, 0x5840665AA752B3C1L, 0x8E314454E9012A9FL, 0x61CAEAD319E9981BL, 0xCC7081080BB6D5B8L, 0xABA8BB6FF55B3A22L, 0xEB37C50AD74BD9EAL, 0x87C193F38E106B59L, 0x7AE2B92A2A06667EL, 0x167AD510120F3519L, 0x4F484EF729456977L, 0x41CBC099DF66C930L, 0x72C0D54CE88A11E4L, 0x4F87AA56BC8411CL, 0x5511F77F83924ACEL, 0x450E86F8ABDE92E0L, 0xB82ACDDB65342993L, 0x2BCFF6E476684150L, 0x4EF5A68495DD29BCL, 0x3A7B0BEEB9B4218AL, 0x54DF89F13BF7E3C6L, 0xEE51506714F8543DL, 0xAA35661A8E18DA7FL, 0x2348EBC95CC83CFCL, 0x3587C132B2655B81L, 0x63AC28411F7A661FL, 0x2864DD48DBD8CC5L, 0xB85266DBEFF85E14L, 0x215466D55B6A95AL, 0xFE20B676F5FB1076L, 0x52339DC61AFB64EDL, 0x3530C5FB6BD98A39L, 0xFAB1E67BF9C08C4EL, 0xCA50C817EA141EA9L, 0x762B93D15A8BA84L, 0xF48BBB6DB2DE4CL, 0x63F1B9D25836E47EL, 0x17037CA5B4724479L, 0x6DACAA582F6117E5L, 0x2B2707D69A1D1993L, 0xED163DD76C8F3BD4L, 0x978EF15DF82677F0L, 0x6899AF31C57E7114L, 0x9062E17D624D6B44L, 0xB6D2765023E165F8L, 0xA4CCFBC17F92B75BL, 0xBED55BB48502AD13L, 0x5DE535FC395233EBL, 0x55430C23CF85F292L, 0xE794C43CAB089B57L, 0x6E6B1A491C81D1A8L, 0xCE08015F38B1F6C1L, 0x6AD30FAE1926764AL, 0xD5C92C3177FFD166L, 0x19A3EE3045598BC1L, 0xE9A34B255C9A0A88L, 0x9E1D6DE11235DB05L, 0xB6883B66747605AFL, 0x769432FD7B16FEB5L, 0xC16DBE1B784AB61L, 0x96E5E9D7269FA8ECL, 0xAFDBA38BD65CA936L, 0x8233BC7E5230C17EL, 0x1AD422B3CB301B2EL, 0x4B40790A37E205F4L, 0x17926D88E8C0A8DEL, 0x1BE691F4948D3328L, 0xECD82FE26FC76142L, 0x421A1BA502248A07L, 0xC9829825D5FE36C7L, 0x6EA9D218F1DE2D36L, 0xE10FDF8EEE0173CBL, 0x1C4361FBD3A8E9AL, 0xE47EA82E0F617609L, 0x481431E3BCD3DB4AL, 0xA3E2D1C4C30BAA28L, 0x14D00FA381C2B3A1L, 0x8426F61FDED27323L, 0xF5389B577120AEAAL, 0x6D1CB41FE24E6900L, 0x114EC6ABEB71AFA5L, 0x617C1BF32EA477F4L, 0x7D764D827A46C865L, 0xA161CB7927D86496L, 0xD5F9B1FB3D1AD344L, 0x92421DEB2ACCA332L, 0xFCFB4C4145DED618L, 0x7B6AA6A979249A5FL, 0xE8EA5BBE742CF914L, 0xB0FAEC4EC552E661L, 0xEFC5B50819661AFAL, 0xF690FC2A1AF451AFL, 0x3BBB71571357A94CL, 0x91BBE9E31B7423ECL, 0x4FD4E61980AF0152L, 0x462D6DEDBA1DCBBDL, 0x1E2F419B91E06D9FL, 0xEEA362F815262060L, 0xD95415140C3A8C25L, 0xC7120AC5AFA9CADL, 0x8B80183FB3C5EEA9L, 0xA27344D633FDFAD5L, 0x9DA16AB99331B7C1L, 0x3F6FDE97052D0F1FL, 0x68B73163DB1D387BL, 0xE08F10B8DF6571CL, 0xC5052D3D36162FC5L, 0x5A0E9A3C466F2062L, 0x9456CCF5D09DE275L, 0xECCCFD9F3591802L, 0x96E7CA508EA5E706L, 0x712B0AD4E5EFDA62L, 0x997675864DD563EBL, 0x4EAA1456D1DF6500L, 0x9959E44016E92022L, 0xCC8CE93DA2B99126L, 0x7B273FEE917E2484L, 0xE129C3F3219F2F98L, 0x99DF6E29A37EFAB2L, 0x6797546EB2A854B0L, 0xCA8A0D7CFC12208BL, 0xA07531A3899F000L, 0xCD4A6DFA10001A19L, 0xF0C73ECFCCDBE606L, 0x8766AAA087581CD9L, 0x57BAFAA8AF13FB74L, 0x7F995CADA881F50DL, 0x5CEB6E1AA89E451BL, 0x2F6515D5DD874796L, 0x7771496FC5E37598L, 0xCAAE3CCCCF5F60ACL, 0x59728E963B862F3EL, 0x807A3F0FD59C5AB3L, 0x6F955E5E9878866DL, 0xDE9043106189FC93L, 0x4D82BE67D74AFE86L, 0x22E0BA028EE42506L, 0x5D5B36275255478BL, 0xB871717D72669E7BL, 0x6B79BCF2DC3A7640L, 0x9B0D0E883DAF5870L, 0xA09B5F4FCDA3D3C9L, 0xC170A6EC2B675A9CL, 0x74DBC97815B388EFL, 0xA2DA67105D19B0A5L, 0x1129F99CAAFAFF64L, 0x36EBA84341B5D11CL, 0x1D8DD817DAFD726DL, 0xB19BC9D877A37694L, 0x8A762795DB2CC087L, 0xCF760E96753DBF78L, 0x492003C211F80889L, 0xF783D906C931A650L, 0xD63AB31E3CA42FCBL, 0xA57F17F89BD5D594L, 0xC9CDD2AC252F6C9L, 0xDB0D1F8FA09E200L, 0x9F03888750FD8378L, 0x658F1FB26CE1EB10L, 0x25B5231C62B9C9FEL, 0x4CA5AC9239C723D5L, 0xCD832D5BAE310CD3L, 0x8EC10BD5914CEEBBL, 0x1E544EF6AF006E6EL, 0xA9FEFC0610223C29L, 0x746A8FD6C1209FE9L, 0x8C4E66A8FAC2E5EAL, 0xDF38C7CAD47DB1E8L, 0x5BFB950671076852L, 0x9D6E2E4196F169ACL, 0xF15F470FA5B8E1CDL, 0x474AA67844C8575EL, 0xFC3444A0CD6C0AA6L, 0xD070B3E75AD2A968L, 0x182D265E3CB47622L, 0xA2AB809F212BB19BL, 0x3EE4E7C9119AE00FL, 0x47D35E7710475069L, 0x21CE86EF267D554L, 0xA3D1A2AF03B0A4EEL, 0x13A31F641EAB7163L, 0x376742A86C7EB3FDL, 0x26EA27107967A919L, 0x22041F653726E6EEL, 0xA233DBC1F42967F4L, 0xB1C347EBA25EBA30L, 0x7D5CBB5094BB9570L, 0xA0825FB59E1B6D24L, 0x4247121395B52D9BL, 0xC2CEA4B33EBD1F10L, 0x527EE3F9AD9BE815L, 0x554D0AB8A32AB582L, 0xD8151CE5DC6C0EBBL, 0x57B8C3989E4F4AB7L, 0x954FCBCD6BE6C68AL, 0x844D4CE2BFE8855FL, 0x2C59F453B4B0E35L, 0x6D53C017408BA6BBL, 0x3AC47CC88F4C6299L, 0x6A822A5F9976D7D0L, 0x1E41A35F46ACAAFDL, 0x646E866A486159CBL, 0x8FA8DB006502C5AFL, 0x6C079C8F289C2CE8L, 0xE523C3755BB4D5C2L, 0xFBFC767162592F77L, 0x44D5E08145DB765FL, 0x30C9FD0EF27839AL, 0x14B109328D66A5CEL, 0x892FFC43339E81AFL, 0xEBA2C6C8D14A48F6L, 0x83BA130162B6DCEL, 0xE5ABA303417D8B9AL, 0x10C956A4E9E17164L, 0xD50238F402C9E462L, 0xF4F8929D08F326A8L, 0xE60179C8E9ED9129L, 0x1CD5F1E287340130L}).toString());
            publicKey = ConfigTools.getPublicKey(new ObfuscatedString(new long[]{0x2C87ED45E415530AL, 0x639A68092FBFB102L, 0xE7663DABEF41701DL, 0x3917EC281732F9C7L, 0x690562FFEF126618L, 0x4ABA04F9C3391CB4L, 0x5307AC44CF528ADBL, 0x93092500D1381290L, 0x6D6A61D950467F0CL, 0x19ACBF57C9BF3EC5L, 0x9A58BB40CCED60B6L, 0xA597F8614EBBDB52L, 0x864BF856017524ACL, 0xAABA946229E31666L, 0x1AE5F7880E01A7C2L, 0x8096AC81C754D35CL, 0xA9E2E70D4F52D3BDL, 0xB3C14F79A92B8071L, 0x647B591E0A85EE58L, 0xB0339892F5663BDFL, 0x9CF6F74D052D90D7L, 0xD275E48F13F7B96AL, 0xBA37C959A6EB87F6L, 0xA85348A5C584A72AL, 0xF5032486FB78C950L, 0x7AFB00A956D3E65DL, 0x242DB13298989DD3L, 0xBF01C8DCCBCAF91EL, 0x8A391A806C874B82L, 0x3481C15683A178B4L, 0xDE433025FCB3EC11L, 0x7CBBF5B69C033C0BL, 0xD2C76B7665ECEB58L, 0xA8DEE14E6262D408L, 0xF209ED0BA3F54D0DL, 0x43AC32D54AC2A877L, 0xDAF3F0391C597C9L, 0xF3A35F88112E800BL, 0x70A597995B4B4E69L, 0xE9D71D3F80E8797FL, 0xA92D296C86B38746L, 0x8F37543092EB421L, 0xBF364CA24162E36BL, 0x492C2D06EBEDC60AL, 0x61C9D7983AF4B590L, 0x14DFB5417A2B9B60L, 0xAF7968797015B8C4L, 0xF0062A3D1155745EL, 0xB5707EE8AB40CAC7L, 0xDC0AF3310FEDB8DEL, 0xCA6E2FFBBC9EF80L, 0x98DC8D8BACEF39F3L, 0xD39FDD8A049C342EL, 0x7FAAD4424572B9E7L, 0x90F219E73A977809L, 0xD375BF0EE1C1EEB3L, 0x827E7F686D6CAAB2L, 0xCF0A90DC2FEB749BL, 0x649240115579EA40L, 0x265C09407F81CA52L, 0xF14E7ECEBBD4DA41L, 0x25A8BE552269B813L, 0xD39F0E58D17AF1D9L, 0xB5A652AC73AE00F3L, 0x1D2E184B5B932DF2L, 0xE61A09C9DFFB824L, 0x574A37EF884FC1F7L, 0xB528DA0C3252F521L, 0x1039C98153F483A5L, 0xE9718F11E98774B6L, 0x930F6766D1487140L, 0x5D59BB1BE789FFF8L, 0xE0C0D6DA7EF6F21FL, 0x88D21FCB3E71A477L, 0xEF55F7455C188208L, 0x80D1A9608BFD70F5L, 0x1C072D2CB6F0E8F2L, 0x7D005D7945CDF681L, 0xC122FDC8566F5B6AL, 0x1B635EBA1C0D526L, 0xF56783D1A9F3B1DFL, 0x7D5B42DF5B5F1608L, 0x2C9B77CEA1268F38L, 0xD925D4ED397CECDEL, 0xF0B378C10D7C62E5L, 0x93946CBD9E4D8FAL, 0x8D28965F3EEDCDFDL, 0xB0A6C3FB42C3CE11L, 0x393B11E09DA87055L, 0x5BF91618B746ED56L, 0x4CA46B66BC088C08L, 0x6E11AFC41249956BL, 0x411A185FB85EF733L}).toString());
        } catch (Exception ex) {
            throw new ServiceException(I18N.getLabel(
                    "easyplatform.workspace.invalid", appWorkspacePath));
        }
    }

    /**
     * @param platformOption
     * @param shiroOption
     */
    private void setPlatformOption(String platformOption, String shiroOption) {
        if (config.getSectionProperty("engine", platformOption) != null) {
            String s = config
                    .getSectionProperty("engine", platformOption);
            try {
                int timeout = Integer.parseInt(s);
                config.setSectionProperty("main", shiroOption,
                        String.valueOf((timeout * 1000)));
            } catch (NumberFormatException ex) {
            }
        }
    }

    /**
     * 实始化服务实现
     */
    protected abstract void initEngineService();

    /**
     * 开始提供服务
     */
    public abstract void start();

    /**
     * 初始化命令执行链
     */
    protected void initCommandExecutors() {
        List<CommandInterceptor> interceptors = new ArrayList<CommandInterceptor>();
        interceptors.add(new LogInterceptor());// 先写log
        interceptors.add(new CommandContextInterceptor(commandContextFactory,
                this));// 设置当前操作的Context
        interceptors.add(new MessageProbeInterceptor());// 监控用户请求及结果
        interceptors.add(new ValidationInterceptor());// 检查用户请求的有效性
        interceptors.add(new MessageLogInterceptor());// 写用户请求及结果到资源（文件或数据库)
        interceptors.add(new CommandInvoker());// 最终的调用
        for (int i = 0; i < interceptors.size() - 1; i++) {
            interceptors.get(i).setNext(interceptors.get(i + 1));
        }
        CommandInterceptor first = interceptors.get(0);// 先从LogInterceptor开始
        commandExecutor = new CommandExecutorImpl(first);// 给所有实现ServiceImpl对象使用
        interceptors.clear();
        interceptors = null;
    }

    /**
     * 初始化命令环境工厂
     */
    protected void initCommandContextFactory() {
        commandContextFactory = new CommandContextFactory();
    }

    /**
     * 根据名称和属性获取系统配置项
     *
     * @param name
     * @param attr
     * @return
     */
    public String getPlatformAttribute(String name, String attr) {
        Section section = config.getSection(name);
        if (section == null)
            return null;
        return section.get(attr);
    }

    /**
     * @param attr
     * @return
     */
    public String getPlatformAttribute(String attr) {
        Section section = config.getSection("engine");
        return section.get(attr);
    }

    /**
     * 获取工作目录
     *
     * @return
     */
    public String getWorkspace() {
        return appWorkspacePath;
    }

    public String getAppTemplatePath() {
        return appTemplatePath;
    }

    /**
     * Web端工作目录，默认值apps
     *
     * @return
     */
    public String getAppPath() {
        return "apps";
    }

    /**
     * 返回Web端工作路径
     *
     * @return
     */
    public String getWebPath() {
        return webApps;
    }

    /**
     * 返回前端模板路径
     *
     * @return
     */
    public String getWebTemplatePath() {
        return webTemplatePath;
    }

    /**
     * 获取web端工作空间
     *
     * @return
     */
    public String getWebWorkspacePath() {
        return webWorkspacePath;
    }

    /**
     * @return
     */
    public String getHome() {
        return properties.get("easyplatform.home");
    }

    /**
     * @param attr
     * @return
     */
    public int getPlatformAttributeAsInt(String attr) {
        Section section = config.getSection("engine");
        return Nums.toInt(section.get(attr), 0);
    }

    /**
     * 获取系统配置项
     *
     * @param name
     * @return
     */
    public Section getAttributes(String name) {
        return config.getSection(name);
    }

    /**
     * 判断是否保持会话存活
     *
     * @return
     */
    public boolean isSessionKeepAlive() {
        boolean keepAlive = false;
        String s = getPlatformAttribute("sessionKeepAlive");
        if (s != null && s.toLowerCase().equals("true"))
            keepAlive = true;
        return keepAlive;
    }

    /**
     * 获取用户会话干超时设定
     *
     * @return
     */
    public int getSessionTimeout() {
        int timeout = 0;
        String s = getPlatformAttribute("sessionTimeout");
        if (s != null) {
            try {
                timeout = Integer.parseInt(s);
            } catch (NumberFormatException ex) {
            }
            if (timeout <= 0)
                timeout = (int) AbstractSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT / 1000;
        } else
            timeout = (int) AbstractSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT / 1000;
        return timeout;
    }

    /**
     * 获取参数数据源
     *
     * @return
     */
    public EntityDao getEntityDao() {
        lock.readLock().lock();
        try {
            ApplicationService service = services.get(SystemServiceId.SYS_ENTITY_DS);
            if (service == null)
                throw new EntityNotFoundException(
                        EntityType.RESOURCE.getName(), SystemServiceId.SYS_ENTITY_DS);
            return DaoFactory.createEntityDao((DataSource) service);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 根据服务ID获取服务对象
     *
     * @param id
     * @return
     */
    public ApplicationService getService(String id) {
        lock.readLock().lock();
        try {
            return services.get(id);
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 新增服务
     *
     * @param s
     * @param s
     */
    public ApplicationService addService(ApplicationService s) {
        lock.writeLock().lock();
        try {
            if (s instanceof IProjectService)
                projectServices.put(s.getId(), (IProjectService) s);
            if (s instanceof AbstractService)
                ((AbstractService) s).setEngineConfiguration(this);
            services.put(s.getId(), s);
            return s;
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 移除服务
     *
     * @param s
     */
    public void removeService(ApplicationService s) {
        lock.writeLock().lock();
        try {
            if (s instanceof IProjectService)
                projectServices.remove(s.getId());
            services.remove(s.getId());
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 获取项目对象
     *
     * @param id
     * @return
     */
    public IProjectService getProjectService(String id) {
        return projectServices.get(id);
    }

    /**
     * 获取所有项目对象
     *
     * @return
     */
    public Collection<IProjectService> getProjectServices() {
        return Collections.unmodifiableCollection(projectServices.values());
    }

    /**
     * 获取系统服务对象列表
     *
     * @return
     */
    public Collection<ApplicationService> getServices() {
        return Collections.unmodifiableCollection(services.values());
    }

    /**
     * 根据外部接口获取外部服务对象
     *
     * @param clazz
     * @return
     */
    public <T> T getEngineService(Class<?> clazz) {
        return (T) engineServices.get(clazz);
    }

    /**
     * 获取所有服务对象，注册RPC时使用
     *
     * @return
     */
    public Set<Map.Entry<Class<?>, Object>> getEngineServices() {
        return engineServices.entrySet();
    }

    /**
     * 设置系统属性和值，如果之前已有，返回旧的值
     *
     * @param key
     * @param value
     */
    public Object setApplicationAttribute(String key, Object value) {
        return applicationCache.put(key, value);
    }

    /**
     * 返回指定属性的值
     *
     * @param key
     * @return
     */
    public Object getApplicationAttributeValue(String key) {
        return applicationCache.get(key);
    }

    /**
     * 移除系统属性，并返回属性值
     *
     * @param key
     * @return
     */
    public Object removeApplicationAttribute(String key) {
        return applicationCache.remove(key);
    }

    /**
     * 缓存线程池
     *
     * @return
     */
    public ThreadPoolExecutor getKernelThreadPoolExecutor() {
        return kernelThreadPoolExecutor;
    }

    /**
     * 缓存管理器
     *
     * @return
     */
    public ICacheManager getCacheManager() {
        return cacheManager;
    }

    /**
     * 计划任务管理器
     *
     * @return
     */
    public IScheduleService getScheduleService() {
        return (IScheduleService) services.get(SystemServiceId.SYS_SCHEDULER);
    }

    /**
     * 获取私钥
     *
     * @return
     */
    public PrivateKey getPrivateKey() {
        return privateKey;
    }

    /**
     * 获取公钥
     *
     * @return
     */
    public PublicKey getPublicKey() {
        return publicKey;
    }

    /**
     * 获取日志保存路径
     *
     * @return
     */
    public String getLogPath() {
        return properties.get("easyplatform.log");
    }

    /**
     * 获取平台任务执行对象
     *
     * @return
     */
    public abstract TaskExecuter getTaskExecuter(CommandContext cc);

    /**
     * 添加应用侦听者
     *
     * @param listener
     */
    public void setApplicationListener(ApplicationListener listener) {
        this.applicationListener = listener;
    }

    /**
     * 获取应用侦听者
     *
     * @return
     */
    public ApplicationListener getApplicationListener() {
        return this.applicationListener;
    }
}